﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using DL.Tools;
using OfficeOpenXml;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;

#if UNITY_EDITOR


public static class ExcelParser
{
    private static readonly string ExcelDir = Application.dataPath + "/DataConfig/Xlsx";

    private static bool isBreak;
    private static float progress;
    private static DataParser curDP;
    
    
    /// <summary>
    /// 不需要解析的Excel
    /// </summary>
    private static readonly List<Type> _unusedDPList = new List<Type>
    {
        
    };
#if UNITY_EDITOR
    [MenuItem("Tools/解析表格")]
    public static void Gen()
    {
        var dir = new DirectoryInfo(ExcelDir);  
        var xlsxList = dir.GetFiles().Where(file => file.Name.EndsWith(".xlsx")).ToList();
        // var nameList = xlsxList.Select(file => file.Name.Substring(0, file.Name.Length - 5)).ToList();
        // var exceptList = _excelDic.Keys.Except(nameList).ToList(); //两个集合的差集，用于检测本地配置表是否完整
        // if (exceptList.Count != 0)
        // {
        //     var builder = new StringBuilder();
        //     builder.AppendLine("缺少所需表，是否继续生成");
        //     foreach (var name in exceptList)
        //     {
        //         Debugger.EO_Log(name + " " + _excelDic[name], Color.red);
        //         builder.AppendLine(name + " " + _excelDic[name]);
        //     }
        //
        //     var ok = EditorUtility.DisplayDialog("配置文件生成确认", builder.ToString(), "继续", "取消");
        //     if (!ok)
        //         return;
        // }

        Load(xlsxList.Select(file => file.FullName).ToArray(), true);
    }
#endif

    public static void Load(IList<string> paths, bool isGenAll = false)
    {
        var assembly = typeof(DataParser).Assembly;
        var idDpDic = new Dictionary<string, DataParser>();
        var dpDic = new Dictionary<string, List<DataParser>>();
        var dpList = new List<DataParser>();
        foreach (var type in assembly.GetTypes())
        {
            if (type.BaseType == typeof(DataParser) && !type.IsAbstract && !_unusedDPList.Contains(type))
            {
                var parser = (DataParser)Activator.CreateInstance(type);
                var csvName = parser.GetLocalCsvName();
                if (string.IsNullOrEmpty(csvName))
                    continue;

                // if (type != typeof(DP_AcePlane))
                //     continue;


                var name = parser.GetLocalCsvName().Split('|')[0];
                if (name.Contains("*"))
                    idDpDic[name] = parser;
                else
                {
                    if (!dpDic.ContainsKey(name))
                        dpDic[name] = new List<DataParser>();
                    dpDic[name].Add(parser);
                }

                dpList.Add(parser);
            }
        }

        isBreak = false;
        EditorApplication.update = () =>
        {
            try
            {
                progress = 0;
                for (var i = 0; i < paths.Count; i++)
                {
                    var path = paths[i];
                    Load(path, idDpDic, dpDic, dpList);
                    progress = (i + 1) * 1.0f / paths.Count;
                    if (isBreak)
                        break;
                }

                if (!isBreak && isGenAll)
                {
                    if (dpList.Count != 0)
                    {
                        Debugger.EO_Log(
                            "excel中所缺少的表" + string.Join("|",dpList.Select(parser => parser.GetLocalCsvName()).ToList()),
                            Color.red);
                        
                        Debugger.EO_Log(
                            "对应DP类名" +  string.Join("|",dpList.Select(parser => parser.GetType().Name).ToList()),
                            Color.yellow);
                        Debugger.EO_Log("配置错误",Color.red);
                    }
                    else
                    {
                        Debugger.EO_Log("全部配置生成成功。", Color.green);
                    }
                }
            }
            catch (Exception e)
            {
                if (curDP != null)
                    Debug.LogError(curDP.GetType().Name + "解析错误, 表名" + curDP.GetLocalCsvName());

                Debug.LogError(e);
            }
            finally
            {
                EditorUtility.ClearProgressBar();
                EditorApplication.update = null;
            }
        };
    }
    
    
    private static void Load(string path, 
        IDictionary<string, DataParser> _idDpDic, 
        IDictionary<string, List<DataParser>> _dpDic, 
        ICollection<DataParser> _dpList)
    {
        var fileInfo = new FileInfo(path);
        isBreak = EditorUtility.DisplayCancelableProgressBar("excel加载中", "加载" + fileInfo.Name, progress);
        if (isBreak)
        {
            EditorApplication.update = null;
            EditorUtility.ClearProgressBar();
            return;
        }

        // var stream = File.Open(path, FileMode.Open, FileAccess.Read);
        // ExcelPackage.LicenseContext = LicenseContext.NonCommercial; //Epplus 证书  
        // try
        // {
        //     using (ExcelPackage package = new ExcelPackage(stream))
        //     {
        //         ExcelWorksheet sheet1 = package.Workbook.Worksheets.FirstOrDefault();
        //         if (sheet1 == null) throw new Exception("can open sheet1");
        //
        //         int rowcnt = sheet1.Rows.Count();
        //         string endcol = sheet1.Columns.Range.LocalAddress.Split(':')[1];//获取最后一列列号
        //         var xls1 = new DataTable();
        //         xls1 = sheet1.Cells[$"A1:{endcol}{rowcnt - 1}"].ToDataTable(); //读取到DataTable
        //
        //         dataGridView1.DataSource = xls1;
        //     }
        // }
        // catch (Exception ex)
        // {
        //     Console.WriteLine($"error:{ex.Message}");
        //     Debugger.EO_Log($"提示：{ex.Message} \n错误：{ex.StackTrace}", Color.red);
        // }
        
        // var reader = ExcelReaderFactory.CreateOpenXmlReader(stream); //读取excel
        // var excel = reader.AsDataSet(new ExcelDataSetConfiguration //作为DataSet存储
        // {
        //     // 不加这个的话，AsDataSet会报InvalidCastException
        //     UseColumnDataType = false
        // });
        
        
        // reader.Close();
        var excel = ReadExcelToDataTable(path);
        var excelName = fileInfo.Name[..^5];
        var tableDic = new Dictionary<string, DataTable>();
        for (var i = 0; i < excel.Tables.Count; i++)
        {
            var name = excelName + " - " + excel.Tables[i].TableName;
            tableDic.Add(name, excel.Tables[i]);
        }
        
        foreach (var dpData in _idDpDic)
        {
            var prefix = dpData.Key.Replace("*", "");
            var tables = tableDic.Where(tableData => tableData.Key.StartsWith(prefix)).ToList();
            if (tables.Count != 0)
            {
                foreach (var tableData in tables)
                {
                    var str = tableData.Key[prefix.Length..];
                    var id = string.IsNullOrEmpty(str) ? 1 : int.Parse(str);
                    dpData.Value.DoParse(tableData.Value, id);
                }

                _dpList.Remove(dpData.Value);
            }
        }

        foreach (var kv in _dpDic)
        {
            if (!tableDic.ContainsKey(kv.Key))
                continue;

            isBreak = EditorUtility.DisplayCancelableProgressBar("excel解析中", "解析" + kv.Key, progress);
            if (isBreak)
                return;

            foreach (var parser in kv.Value)
            {
                if (_unusedDPList.Contains(parser.GetType()))
                    continue;

                var csvNames = parser.GetLocalCsvName().Split('|');
                _dpList.Remove(parser);
                if (csvNames.Length == 1)
                {
                    curDP = parser;
                    parser.DoParse(tableDic[kv.Key]);
                    curDP = null;
                }
                else
                {
                    var tables = csvNames.Select(name => tableDic[name]).ToArray();
                    curDP = parser;
                    parser.DoParse(tables);
                    curDP = null;
                }
            }
        }
    }
    
    public static DataSet ReadExcelToDataTable(string filePath)
    {
        using (var package = new ExcelPackage(new FileInfo(filePath)))
        {
            // 获取Excel工作表
            var worksheets = package.Workbook.Worksheets;
            var ds = new DataSet();
            foreach (var worksheet in worksheets)
            {
                Debugger.EO_Log(worksheet.Name,Color.red);
                var dt = new DataTable(worksheet.Name);
                // 获取工作表中的数据
                var start = worksheet.Dimension.Start;//左上
                var end = worksheet.Dimension.End;//右下
                Debugger.EO_Log($"左上{start.Row}:{start.Column},右下{end.Row}:{end.Column}", Color.cyan);
                // 遍历工作表中的所有单元格
                for (int row = start.Row; row <= end.Row; row++)//行
                {
                    // 创建数据表列
                    if (row == start.Row)
                    {
                        for (int col = start.Column; col <= end.Column; col++)
                        {
                            // dt.Columns.Add(worksheet.Cells[row, col].Value?.ToString());//可能为空
                            dt.Columns.Add((col - 1).ToString());
                        }
                    }
                    // else
                    {
                        // 创建数据表行
                        var dataRow = dt.NewRow();
                        // Debugger.EO_Log(dt.Columns[start.Column - 1].ColumnName, Color.blue);
                        // Debugger.EO_Log(worksheet.Cells[row, 1].Value?.ToString(), Color.yellow);
                        for (int col = start.Column; col <= end.Column; col++)
                        {
                            dataRow[dt.Columns[col - 1].ColumnName] = worksheet.Cells[row, col].Value?.ToString();
                        }
                        dt.Rows.Add(dataRow);
                    }
                }
                ds.Tables.Add(dt.Copy());
            }
            return ds;
        }
    }
}
#endif
